package org.xteam.sled.semantic;

import java.util.ArrayList;
import java.util.List;

import org.xteam.sled.ast.DefaultSledVisitor;
import org.xteam.sled.ast.Generator;
import org.xteam.sled.ast.IntegerLiteral;
import org.xteam.sled.ast.ListGenerator;
import org.xteam.sled.ast.RangeGenerator;
import org.xteam.sled.semantic.exp.ExpConst;


public class GeneratorIntegerSemantic extends DefaultSledVisitor {

	private List<ExpConst> result;
	private IEvaluationContext context;
	
	public GeneratorIntegerSemantic(IEvaluationContext context) {
		this.context = context;
	}
	
	public List<ExpConst> analyse(Generator generator) {
		generator.visit(this);
		return result;
	}

	// app (A.LIST, es)   = emap (GROUP o single) (elabInts es)
	public void visitListGenerator(ListGenerator generator) {
		result = new ArrayList<ExpConst>();
		for (IntegerLiteral i : generator.getValues()) {
			result.add(new ExpConst(i.getValue()));
		}
	}

	// app (A.GEN_to, es) = emap (GROUP o genlist o (map insistInt) o single) (elabInts es)
	public void visitRangeGenerator(RangeGenerator generator) {
		int from = generator.getFrom().getValue();
		int to = generator.getTo().getValue() + 1;
		int step = generator.getStep() == null ? 1 : generator.getStep().getValue();
		int rows = (to - from) / step;
		if (((to - from) % step) == 0) {
			int base = from;
			result = new ArrayList<ExpConst>();
			for (int row = 0; row < rows; ++row) {
				int c = base;
				for (int col = 0; col < step; ++col) {
					result.add(new ExpConst(c));
					c += rows;
				}
				++base;
			}
		} else {
			context.reportError(generator.span(), "bad generator"
       			+ (to - from) + " elements won't fit in "+ step + " columns");
		}
	}
}
